home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / audio / drive / Cockpit.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  19.9 KB  |  966 lines

  1. /*
  2.  * Copyright 1992-1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. //////////////////////////////////////////////////////////////////////
  18. // Cockpit.c++ - implementation of the cockpit class
  19. //
  20. //
  21. // XXX Really should split this into static and dynamics portions
  22. // of the dash.
  23. //////////////////////////////////////////////////////////////////////
  24.  
  25.  
  26. #include "Cockpit.h"
  27. #include "Car.h"
  28. #include "Engine.h"
  29. #include "Dynamics.h"
  30. #include "Render.h"
  31. #include "Driver.h"
  32. #include "Icon.h"
  33. #include "Timer.h"
  34. #include "Indicators.h"
  35.  
  36. Cockpit::Cockpit(Car *c)
  37. {
  38.     _car = c;
  39.  
  40.     _gas = _brakes = _clutch = _steering = 0.0;
  41.     
  42.     // XXX read this stuff from a file
  43.     _steering_pos.setValue(7.8,-.7,0.0);
  44.     
  45.     _tach_pos.setValue(_steering_pos[0] - 2.2, 3.0, 0.0);
  46.     _tach_size = 2.0;
  47.     
  48.     _speedo_pos.setValue(_steering_pos[0] + 2.2, 3.0, 0.0);
  49.     _speedo_size = 2.0;
  50.  
  51.     _gas_pos.setValue(17.5,3.0,0.0);
  52.     _gas_size = 1.5;
  53.  
  54.     _temp_pos.setValue(19.75,3.0,0.0);
  55.     _temp_size = 1.5;
  56.     
  57.     _oil_pos.setValue(17.5,.75,0.0);
  58.     _oil_size = 1.5;
  59.     
  60.     _fps_pos.setValue(19.75,.75,0.0);
  61.     _fps_size = 1.5;
  62.  
  63.     _gear_pos.setValue(15.0,_oil_pos[1], 0.0);
  64.     _gear_width = .5;
  65.     _gear_height = _gas_pos[1] - _oil_pos[1] + _gas_size + .1;
  66.  
  67.     _timer_pos.setValue(20.5,.6,0.0);
  68.     _timer_width = 2.5;
  69. }
  70.  
  71.  
  72. Cockpit::~Cockpit()
  73. {
  74. }
  75.  
  76.  
  77. // draws the static portions of the cockpit
  78. void Cockpit::draw_cockpit(int window_width)
  79. {
  80.     ortho(0.0,25.0,0.0,6.5,-10.0,10.0);
  81.     _world_per_pixel = 25.0/(float)window_width;
  82.     
  83.     Boolean last_zbuffer = getzbuffer();
  84.     Boolean last_backface = getbackface();
  85.     long last_shademodel = getsm();
  86.     
  87.     cpack(0);
  88.     clear();
  89.  
  90.     lmbind(LMODEL,1);
  91.     lmbind(LIGHT0,SUN);
  92.     shademodel(GOURAUD);
  93.     zbuffer(FALSE);
  94.     backface(TRUE);
  95.     
  96.     draw_dash();
  97.     draw_steering_wheel();
  98.     draw_gages(_world_per_pixel);
  99.     draw_icons();
  100.  
  101.     lmbind(LMODEL,0);
  102.     lmbind(LIGHT0,0);
  103.     shademodel(last_shademodel);
  104.     zbuffer(last_zbuffer);
  105.     backface(last_backface);
  106.  
  107.     draw_indicators(TRUE);
  108. }
  109.  
  110.  
  111. // called when the window is resized to clear the overlay crap
  112. void Cockpit::clear_indicators() const
  113. {
  114.     drawmode(PUPDRAW);
  115.     
  116.     color(CLEAR);
  117.     clear();
  118.  
  119.     drawmode(NORMALDRAW);
  120. }
  121.  
  122.  
  123. void Cockpit::draw_indicators(Boolean redraw) const
  124. {
  125.     ortho2(0.0,25.0,0.0,6.5);
  126.  
  127.     Boolean last_zbuffer = getzbuffer();
  128.     Boolean last_backface = getbackface();
  129.     long last_shademodel = getsm();
  130.     
  131.     // sync up (as much as posiible) so overlay drawing happens
  132.     // during vertical retrace
  133.     // XXX double buffer overlays, if possible
  134.     gsync();
  135.  
  136.     drawmode(PUPDRAW);
  137.     zbuffer(FALSE);
  138.     backface(FALSE);
  139.     shademodel(FLAT);
  140.  
  141.     if (redraw)
  142.     {
  143.         color(CLEAR);
  144.         clear();
  145.     }
  146.     
  147.     // draw back to front
  148.     draw_needles(redraw); // temp, gas, etc
  149.     draw_overlapping_needles(redraw); // speedo, tach and steering spokes
  150.     draw_messages(redraw);
  151.     draw_times(redraw,_world_per_pixel);
  152.  
  153.     drawmode(NORMALDRAW);
  154.     zbuffer(last_zbuffer);
  155.     backface(last_backface);
  156.     shademodel(last_shademodel);
  157. }
  158.  
  159.  
  160. void Cockpit::draw_timer(float width, float world_per_pixel) const
  161. {
  162.     fmfonthandle font1 = fmfindfont("Hlv");
  163.     float pnt_size = (width/world_per_pixel)/8.0;
  164.     fmfonthandle font = fmscalefont(font1, pnt_size);
  165.     fmsetfont(font);
  166.     
  167.     cpack(ORANGE);
  168.     
  169.     cmov2(0.0,2.6);
  170.     fmprstr("This Lap");
  171.         
  172.     cmov2(0.0,1.6);
  173.     fmprstr("Last Lap");
  174.         
  175.     cmov2(0.0,.6);
  176.     fmprstr("Best Lap");
  177.  
  178.     cpack(0);
  179.     sboxf(0.0,0.0,width,0.5);
  180.     sboxf(0.0,1.0,width,1.5);
  181.     sboxf(0.0,2.0,width,2.5);
  182. }
  183.  
  184.  
  185. void Cockpit::draw_times(Boolean redraw, float world_per_pixel) const
  186. {
  187.     static fmfonthandle font1, font;
  188.     static float last_world_per_pixel = -1.0;
  189.  
  190.     if (world_per_pixel != last_world_per_pixel)
  191.     {
  192.         font1 = fmfindfont("HlvB");
  193.         font = fmscalefont(font1, .45/world_per_pixel);
  194.  
  195.         last_world_per_pixel = world_per_pixel;
  196.     }
  197.  
  198.     fmsetfont(font);
  199.  
  200.     char *buf;
  201.  
  202.     if (_car->get_driver()->get_timer()->get_this_lap(buf) || redraw)
  203.     {
  204.         color(CLEAR);
  205.         sboxf(_timer_pos[0]-.2,_timer_pos[1]+2.0,
  206.             _timer_pos[0]+_timer_width+.2,_timer_pos[1]+2.5);
  207.         color(GREY2);
  208.         cmov2(_timer_pos[0],_timer_pos[1]+2.0);
  209.         fmprstr(buf);
  210.     }
  211.     
  212.     if (_car->get_driver()->get_timer()->get_last_lap(buf) || redraw)
  213.     {
  214.         color(CLEAR);
  215.         sboxf(_timer_pos[0]-.2,_timer_pos[1]+1.0,
  216.             _timer_pos[0]+_timer_width+.2,_timer_pos[1]+1.5);
  217.         color(GREY2);
  218.         cmov2(_timer_pos[0],_timer_pos[1]+1.0);
  219.         fmprstr(buf);
  220.     }
  221.     
  222.     if (_car->get_driver()->get_timer()->get_best_lap(buf) || redraw)
  223.     {
  224.         color(CLEAR);
  225.         sboxf(_timer_pos[0]-.2,_timer_pos[1],
  226.             _timer_pos[0]+_timer_width+.2,_timer_pos[1]+0.5);
  227.         color(GREY2);
  228.         cmov2(_timer_pos[0],_timer_pos[1]);
  229.         fmprstr(buf);
  230.     }
  231. }
  232.  
  233.  
  234.  
  235. // XXX really need an indicator class that handles all this
  236. void Cockpit::draw_needles(Boolean redraw) const
  237. {
  238.     // gas
  239.     pushmatrix();
  240.         translate(_gas_pos[0], _gas_pos[1], _gas_pos[2]);
  241.  
  242.         static float last_gas = -1.0;
  243.         float gas = (_car->get_engine()->get_gas());
  244.         if (redraw || (gas != last_gas))
  245.         {
  246.             static float last_gas_angle = 0.0;
  247.             pushmatrix();
  248.                 rotate((short)last_gas_angle,'z');
  249.                 scale(_gas_size,1.0,1.0);
  250.                 draw_needle(FALSE);
  251.             popmatrix();
  252.             
  253.             float angle = - 900.0 * gas / _car->get_engine()->get_max_gas();
  254.             rotate((short)angle,'z');
  255.             scale(_gas_size,1.0,1.0);
  256.             draw_needle(TRUE);
  257.  
  258.             last_gas = gas;
  259.             last_gas_angle = angle;
  260.         }
  261.     popmatrix();
  262.  
  263.     // temp
  264.     pushmatrix();
  265.         translate(_temp_pos[0], _temp_pos[1], _temp_pos[2]);
  266.  
  267.         static float last_temp = -1.0;
  268.         float temp = (_car->get_engine()->get_temp());
  269.         if (redraw || (temp != last_temp))
  270.         {
  271.             static float last_temp_angle = 0.0;
  272.             pushmatrix();
  273.                 rotate((short)last_temp_angle,'z');
  274.                 scale(_temp_size,1.0,1.0);
  275.                 draw_needle(FALSE);
  276.             popmatrix();
  277.             
  278.             float angle = - 900.0 * temp / _car->get_engine()->get_max_temp();
  279.             rotate((short)angle,'z');
  280.             scale(_temp_size,1.0,1.0);
  281.             draw_needle(TRUE);
  282.  
  283.             last_temp = temp;
  284.             last_temp_angle = angle;
  285.         }
  286.     popmatrix();
  287.     
  288.     // oil
  289.     pushmatrix();
  290.         translate(_oil_pos[0], _oil_pos[1], _oil_pos[2]);
  291.  
  292.         static float last_oil = -1.0;
  293.         float oil = (_car->get_engine()->get_oil());
  294.         if (redraw || (oil != last_oil))
  295.         {
  296.             static float last_oil_angle = 0.0;
  297.             pushmatrix();
  298.                 rotate((short)last_oil_angle,'z');
  299.                 scale(_oil_size,1.0,1.0);
  300.                 draw_needle(FALSE);
  301.             popmatrix();
  302.             
  303.             float angle = - 900.0 * oil / _car->get_engine()->get_max_oil();
  304.             rotate((short)angle,'z');
  305.             scale(_oil_size,1.0,1.0);
  306.             draw_needle(TRUE);
  307.  
  308.             last_oil = oil;
  309.             last_oil_angle = angle;
  310.         }
  311.     popmatrix();
  312.  
  313.     
  314.     // fps
  315.     pushmatrix();
  316.         translate(_fps_pos[0], _fps_pos[1], _fps_pos[2]);
  317.  
  318.         static float last_fps = -1.0;
  319.         float fps = (_car->get_driver()->get_fps());
  320.         if (redraw || (fps != last_fps))
  321.         {
  322.             static float last_fps_angle = 0.0;
  323.             pushmatrix();
  324.                 rotate((short)last_fps_angle,'z');
  325.                 scale(_fps_size,1.0,1.0);
  326.                 draw_needle(FALSE);
  327.             popmatrix();
  328.             
  329.             float angle = - 900.0 * fps / _car->get_driver()->get_max_fps();
  330.             rotate((short)angle,'z');
  331.             scale(_fps_size,1.0,1.0);
  332.             draw_needle(TRUE);
  333.  
  334.             last_fps = fps;
  335.             last_fps_angle = angle;
  336.         }
  337.     popmatrix();
  338.     
  339.     
  340.     
  341.     // gear indicator
  342.     static int last_gear = -999;
  343.     int gear = (_car->get_engine()->get_gear());
  344.     if (redraw || (last_gear != gear))
  345.     {
  346.         float rect_size = 3.0*_gear_width/4.0;
  347.         
  348.         pushmatrix();
  349.             translate(_gear_pos[0], _gear_pos[1], _gear_pos[2]);
  350.             translate(_gear_width/2.0, _gear_height/2.0, 0.0);
  351.             scale(_gear_height/6.0,_gear_height/6.0,_gear_height/6.0);
  352.             pushmatrix();
  353.                 translate(0.0,(float)last_gear-2.0,0.0);
  354.                 color(CLEAR);
  355.                 rect(-rect_size,-rect_size,rect_size,rect_size);
  356.             popmatrix();
  357.             translate(0.0,(float)gear-2.0,0.0);
  358.             color(GREY2);
  359.             rect(-rect_size,-rect_size,rect_size,rect_size);
  360.         popmatrix();
  361.     }
  362.     last_gear = gear;
  363. }
  364.  
  365.  
  366. void Cockpit::draw_tachometer(float diam, float world_per_pixel) const
  367. {
  368.     // draw red zone
  369.  
  370.     static float a[2], b[2];
  371.     a[0] = b[0] = 0.0;
  372.     a[1] = - diam;
  373.     b[1] = - .9*diam;
  374.  
  375.     float angle = 
  376.         270.0*(float)(_car->get_engine()->get_max_rpm() - 
  377.         _car->get_engine()->get_redline())/(float)_car->get_engine()->get_max_rpm();
  378.         
  379.     cpack(MED_RED);
  380.     sweep(a,b,angle);
  381.  
  382.     
  383.     draw_dial(
  384.         diam, world_per_pixel, 
  385.         180.0, -90.0, 
  386.         .95, .9, 
  387.         .75, 
  388.         0, _car->get_engine()->get_max_rpm(),
  389.         200,
  390.         1.0/1000.0,
  391.         5,
  392.         1);
  393.  
  394.     lmbind(LMODEL,1);
  395.     lmbind(LIGHT0,DOME_LIGHT);
  396.     lmbind(MATERIAL, GREY_PLASTIC);
  397.     
  398.     settorus(0.05, 1.025*diam);    
  399.     ftorus();
  400.         
  401.     lmbind(LMODEL,0);
  402.     lmbind(LIGHT0,0);
  403.     lmbind(MATERIAL, 0);
  404. }
  405.  
  406.  
  407. void Cockpit::draw_speedometer(float diam, float world_per_pixel) const
  408. {
  409.     draw_dial(diam, world_per_pixel, 
  410.         180.0, -90.0, 
  411.         .95, .9, 
  412.         .75, 
  413.         0, _car->get_engine()->get_max_speed(),
  414.         5,
  415.         1.0,
  416.         2,
  417.         2);
  418.  
  419.  
  420.     lmbind(LMODEL,1);
  421.     lmbind(LIGHT0,DOME_LIGHT);
  422.     lmbind(MATERIAL, GREY_PLASTIC);
  423.     
  424.     settorus(0.05, 1.025*diam);    
  425.     ftorus();
  426.         
  427.     lmbind(LMODEL,0);
  428.     lmbind(LIGHT0,0);
  429.     lmbind(MATERIAL, 0);
  430. }
  431.  
  432.  
  433. void Cockpit::draw_gas(float diam, float world_per_pixel) const
  434. {
  435.     draw_dial(
  436.         diam, world_per_pixel, 
  437.         180.0, 90.0,
  438.         .95, .9, 
  439.         .75, 
  440.         0, (int) _car->get_engine()->get_max_gas(),
  441.         2,
  442.         1.0,
  443.         2,
  444.         1);
  445.             
  446. }
  447.  
  448.  
  449. void Cockpit::draw_temp(float diam, float world_per_pixel) const
  450. {
  451.     int max = (int)_car->get_engine()->get_max_temp();
  452.     
  453.     draw_dial(
  454.         diam, world_per_pixel, 
  455.         180.0, 90.0,
  456.         .95, .9, 
  457.         .75, 
  458.         0, max,
  459.         max/4,
  460.         1.0,
  461.         2,
  462.         1);
  463. }
  464.  
  465.  
  466. void Cockpit::draw_oil(float diam, float world_per_pixel) const
  467. {
  468.     int max = (int)_car->get_engine()->get_max_oil();
  469.     
  470.     draw_dial(
  471.         diam, world_per_pixel, 
  472.         180.0, 90.0,
  473.         .95, .9, 
  474.         .75, 
  475.         0, max,
  476.         max/4,
  477.         1.0,
  478.         2,
  479.         1);
  480. }
  481.  
  482.  
  483. void Cockpit::draw_fps(float diam, float world_per_pixel) const
  484. {
  485.     int max = (int)_car->get_driver()->get_max_fps();
  486.     
  487.     draw_dial(
  488.         diam, world_per_pixel, 
  489.         180.0, 90.0,
  490.         .95, .9, 
  491.         .75, 
  492.         0, max,
  493.         max/6,
  494.         1.0,
  495.         2,
  496.         1);
  497. }
  498.  
  499.  
  500. // draws the string at 0.0,0.0
  501. void Cockpit::center_string(
  502.     fmfonthandle font, float world_per_pixel, char *s) const
  503. {
  504.     fmfontinfo font_info;
  505.     fmgetfontinfo(font, &font_info);
  506.     
  507.     long pixels_high = font_info.height;
  508.     long pixels_wide = fmgetstrwidth(font,s);
  509.     
  510.     float world_high = (float)pixels_high*world_per_pixel;
  511.     float world_wide = (float)pixels_wide*world_per_pixel;
  512.  
  513.     cmov2(-world_wide/2.0, -world_high/2.0);
  514.     fmsetfont(font);
  515.     fmprstr(s);
  516. }
  517.  
  518.  
  519. void Cockpit::draw_gear(float width, float height, float world_per_pixel) const
  520. {
  521.     fmfonthandle font1 = fmfindfont("Hlv");
  522.     float pnt_size = (width/world_per_pixel)/2.0;
  523.     fmfonthandle font = fmscalefont(font1, pnt_size);
  524.  
  525.     pushmatrix();
  526.     translate(width/2.0,height/2.0,0.0);
  527.     scale(height/6.0,height/6.0,height/6.0);
  528.  
  529.     cpack(ORANGE);
  530.     pushmatrix();
  531.         translate(0.0,3.0,0.0);
  532.         center_string(font,world_per_pixel,"5");
  533.         translate(0.0,-1.0,0.0);
  534.         center_string(font,world_per_pixel,"4");
  535.         translate(0.0,-1.0,0.0);
  536.         center_string(font,world_per_pixel,"3");
  537.         translate(0.0,-1.0,0.0);
  538.         center_string(font,world_per_pixel,"2");
  539.         translate(0.0,-1.0,0.0);
  540.         center_string(font,world_per_pixel,"1");
  541.         translate(0.0,-1.0,0.0);
  542.         center_string(font,world_per_pixel,"N");
  543.         translate(0.0,-1.0,0.0);
  544.         center_string(font,world_per_pixel,"R");
  545.     popmatrix();
  546.  
  547.     popmatrix();
  548. }
  549.  
  550.  
  551. void Cockpit::draw_gages(float world_per_pixel) const
  552. {
  553.     // tachometer
  554.     pushmatrix();
  555.         translate(_tach_pos[0], _tach_pos[1], _tach_pos[2]);
  556.         draw_tachometer(_tach_size, world_per_pixel);
  557.         cmov2(-_tach_size/3.0,-_tach_size/5.0);
  558.         cpack(ORANGE);
  559.         fmprstr("x1000 / min");
  560.     popmatrix();
  561.  
  562.     // speedometer
  563.     pushmatrix();
  564.         translate(_speedo_pos[0], _speedo_pos[1], _speedo_pos[2]);
  565.         draw_speedometer(_tach_size, world_per_pixel);
  566.         cmov2(-_speedo_size/8.0,-_speedo_size/5.0);
  567.         cpack(ORANGE);
  568.         fmprstr("mph");
  569.     popmatrix();
  570.  
  571.     pushmatrix();
  572.         translate(_gas_pos[0], _gas_pos[1], _gas_pos[2]);
  573.         draw_gas(_gas_size, world_per_pixel);
  574.         cmov2(-_gas_size/2.0,-_gas_size/5.0);
  575.         cpack(ORANGE);
  576.         fmprstr("gal");
  577.     popmatrix();
  578.  
  579.     pushmatrix();
  580.         translate(_temp_pos[0], _temp_pos[1], _temp_pos[2]);
  581.         draw_temp(_temp_size, world_per_pixel);
  582.         cmov2(-_temp_size/2.0,-_temp_size/5.0);
  583.         cpack(ORANGE);
  584.         fmprstr("deg F");
  585.     popmatrix();
  586.  
  587.     pushmatrix();
  588.         translate(_oil_pos[0], _oil_pos[1], _oil_pos[2]);
  589.         draw_oil(_oil_size, world_per_pixel);
  590.         cmov2(-_oil_size/2.0,-_oil_size/5.0);
  591.         cpack(ORANGE);
  592.         fmprstr("psi");
  593.     popmatrix();
  594.  
  595.     pushmatrix();
  596.         translate(_fps_pos[0], _fps_pos[1], _fps_pos[2]);
  597.         draw_fps(_fps_size, world_per_pixel);
  598.         cmov2(-_fps_size/2.0,-_fps_size/5.0);
  599.         cpack(ORANGE);
  600.         fmprstr("fps");
  601.     popmatrix();
  602.  
  603.     pushmatrix();
  604.         translate(_gear_pos[0], _gear_pos[1], _gear_pos[2]);
  605.         draw_gear(_gear_width,_gear_height, world_per_pixel);
  606.     popmatrix();
  607.  
  608.     pushmatrix();
  609.         translate(_timer_pos[0], _timer_pos[1], _timer_pos[2]);
  610.         draw_timer(_timer_width, world_per_pixel);
  611.     popmatrix();
  612.     
  613.     // draw a bulbous box about the gas, oil, temp and fps
  614.     // and around the gear indicator
  615.     lmbind(LMODEL,1);
  616.     lmbind(LIGHT0,DOME_LIGHT);
  617.     lmbind(MATERIAL, GREY_PLASTIC);
  618.  
  619.     /*
  620.     // naah, looks icky
  621.     bulbous_box(
  622.         _oil_pos[0] - _oil_size - .2, _oil_pos[1] - .5,
  623.         _temp_pos[0] + .4, _temp_pos[1] + _temp_size + .25,
  624.         .05);
  625.     */
  626.  
  627.     bulbous_box(
  628.         _gear_pos[0] - .08, _gear_pos[1] - .3,
  629.         _gear_pos[0] + _gear_width + .08, _gear_pos[1] + _gear_height + .3,
  630.         .05);
  631.  
  632.     bulbous_box(
  633.         _timer_pos[0] - .2, _timer_pos[1] - .2,
  634.         _timer_pos[0] + _timer_width + .2, _timer_pos[1] + 3.1,
  635.         .05);
  636.  
  637.     lmbind(LMODEL,0);
  638.     lmbind(LIGHT0,0);
  639.     lmbind(MATERIAL, 0);
  640.  
  641.  
  642.     // label how you get help
  643.     fmfonthandle font1 = fmfindfont("Hlv");
  644.     float pnt_size = (2.0/world_per_pixel)/8.0;
  645.     fmfonthandle font = fmscalefont(font1, pnt_size);
  646.     fmsetfont(font);
  647.     
  648.     cpack(ORANGE);
  649.     pushmatrix();
  650.         translate(_steering_pos[0], 5.3, 0.0);
  651.         center_string(font, world_per_pixel, "Press H for Help");
  652.     popmatrix();
  653. }
  654.  
  655. void Cockpit::draw_messages(Boolean redraw) const
  656. {
  657.     char buf[32];
  658.     static Boolean last_off_road_left = FALSE;
  659.     static Boolean last_off_road_right = FALSE;
  660.     Boolean off_road_left = (_car->get_dynamics()->get_off_road_left());
  661.     Boolean off_road_right = (_car->get_dynamics()->get_off_road_right());
  662.  
  663.     if (redraw || (off_road_left != last_off_road_left))
  664.     {
  665.         if (off_road_left)
  666.             color(GREY3);
  667.         else
  668.             color(CLEAR);
  669.  
  670.         sboxf(0.0,4.0,0.5,5.0);
  671.         bgnpolygon();
  672.             vertex(0.5,3.5);
  673.             vertex(1.0,4.5);
  674.             vertex(0.5,5.5);
  675.         endpolygon();
  676.  
  677.         last_off_road_left = off_road_left;
  678.     }
  679.     
  680.     if (redraw || (off_road_right != last_off_road_right))
  681.     {
  682.         if (off_road_right)
  683.             color(GREY3);
  684.         else
  685.             color(CLEAR);
  686.  
  687.         sboxf(24.5,4.0,25.0,5.0);
  688.         bgnpolygon();
  689.             vertex(24.5,5.5);
  690.             vertex(24.5,3.5);
  691.             vertex(24.0,4.5);
  692.         endpolygon();
  693.  
  694.         last_off_road_right = off_road_right;
  695.     }
  696.  
  697. }
  698.  
  699.  
  700. void Cockpit::draw_overlapping_needles(Boolean redraw) const
  701. {
  702.     float angle;
  703.     
  704.     static float last_rpm = 0.0;
  705.     static float last_speed = 0.0;
  706.     static float last_steering = 0.0;
  707.  
  708.     float rpm = (float)_car->get_engine()->get_rpm();
  709.     float speed = (_car->get_dynamics()->get_velocity());
  710.  
  711.     // don't draw if we don't have to
  712.     if ((!redraw)&&(rpm==last_rpm)&&(speed==last_speed)&&(_steering == last_steering))
  713.         return;
  714.  
  715.     // else we first clear the needles and spokes, then draw them back
  716.     // to front
  717.     
  718.     // clear tachometer
  719.     pushmatrix();
  720.         translate(_tach_pos[0], _tach_pos[1], _tach_pos[2]);
  721.  
  722.         angle = - 2700 * last_rpm / (float) _car->get_engine()->get_max_rpm();
  723.         rotate((short)angle,'z');
  724.         
  725.         scale(_tach_size,1.0,1.0);
  726.         draw_needle(FALSE);
  727.     popmatrix();
  728.     
  729.     // clear speedometer
  730.     pushmatrix();
  731.         translate(_speedo_pos[0], _speedo_pos[1], _speedo_pos[2]);
  732.         
  733.         angle = - 2700 * last_speed / (float) _car->get_engine()->get_max_speed();
  734.         rotate((short)angle,'z');
  735.         
  736.         scale(_speedo_size,1.0,1.0);
  737.         draw_needle(FALSE);
  738.     popmatrix();
  739.  
  740.     // clear the steering spokes
  741.     draw_steering_spokes(FALSE,last_steering);
  742.  
  743.     // draw tachometer
  744.     pushmatrix();
  745.         translate(_tach_pos[0], _tach_pos[1], _tach_pos[2]);
  746.  
  747.         angle = - 2700 * rpm / (float) _car->get_engine()->get_max_rpm();
  748.         rotate((short)angle,'z');
  749.         
  750.         scale(_tach_size,1.0,1.0);
  751.         draw_needle(TRUE);
  752.     popmatrix();
  753.     
  754.     // draw speedometer
  755.     pushmatrix();
  756.         translate(_speedo_pos[0], _speedo_pos[1], _speedo_pos[2]);
  757.         
  758.         angle = - 2700 * speed / (float) _car->get_engine()->get_max_speed();
  759.         rotate((short)angle,'z');
  760.         
  761.         scale(_speedo_size,1.0,1.0);
  762.         draw_needle(TRUE);
  763.     popmatrix();
  764.  
  765.     // draw the steering spokes
  766.     draw_steering_spokes(TRUE,_steering);
  767.  
  768.     last_rpm = rpm;
  769.     last_speed = speed;
  770.     last_steering = _steering;
  771. }
  772.  
  773.  
  774. void Cockpit::draw_steering_wheel() const
  775. {
  776.     pushmatrix();
  777.     
  778.     translate(_steering_pos[0], _steering_pos[1], _steering_pos[2]);
  779.  
  780.     lmbind(LMODEL,1);
  781.     lmbind(LIGHT0,DOME_LIGHT);
  782.     lmbind(MATERIAL, GREY_PLASTIC);
  783.     settorus(0.3, 6.75);    
  784.     ftorus();
  785.     
  786.     lmbind(MATERIAL,0);
  787.     lmbind(LIGHT0,0);
  788.     lmbind(LMODEL,0);
  789.  
  790.     cpack(DARK_GREY);
  791.     circf(0.0,0.0,1.4);
  792.  
  793.     cpack(MED_GREY);
  794.     circf(0.0,0.0,1.35);
  795.  
  796.     cpack(LIGHT_GREY);
  797.     circf(0.0,0.0,1.3);
  798.  
  799.     popmatrix();
  800. }
  801.  
  802.  
  803. void Cockpit::draw_icons() const
  804. {
  805.     Boolean last_backface = getbackface();
  806.     
  807.     backface(FALSE);
  808.     
  809.     pushmatrix();
  810.         translate(_gas_pos[0], _gas_pos[1], _gas_pos[2]);
  811.         translate(-_gas_size,3.0*_gas_size/4.0,0.0);
  812.         scale(.5,.5,.5);
  813.         draw_gas_icon();
  814.     popmatrix();
  815.     
  816.     pushmatrix();
  817.         translate(_oil_pos[0], _oil_pos[1], _oil_pos[2]);
  818.         translate(-_oil_size,4.0*_oil_size/5.0,0.0);
  819.         scale(.5,.5,.5);
  820.         draw_oil_icon();
  821.     popmatrix();
  822.     
  823.     pushmatrix();
  824.         translate(_temp_pos[0], _temp_pos[1], _temp_pos[2]);
  825.         translate(-_temp_size,3.0*_temp_size/4.0,0.0);
  826.         scale(.5,.5,.5);
  827.         draw_temp_icon();
  828.     popmatrix();
  829.     
  830.     pushmatrix();
  831.         translate(_fps_pos[0], _fps_pos[1], _fps_pos[2]);
  832.         translate(-_fps_size,3.0*_fps_size/4.0,0.0);
  833.         scale(.4,.4,.4);
  834.         draw_fps_icon();
  835.     popmatrix();
  836.     
  837.     backface(last_backface);    
  838. }
  839.  
  840.  
  841.  
  842.  
  843.  
  844. void Cockpit::draw_dash() const
  845. {
  846.     lmbind(LIGHT0, DOME_LIGHT);
  847.     lmbind(LMODEL,1);
  848.  
  849.     // draw top rim of dash
  850.     lmbind(MATERIAL, BLACK_PLASTIC);
  851.     pushmatrix();
  852.         translate(12.5,6.25,0.0);
  853.         scale(25.0,0.5,1.0);
  854.         rotate(900,'y');
  855.         fcylinder();
  856.     popmatrix();
  857.     lmbind(MATERIAL,0);
  858.     lmbind(LIGHT0,0);
  859.     lmbind(LMODEL,0);
  860.     
  861.  
  862.     // draw dash background
  863.     static float v1[2] = {0.0,0.0};
  864.     static float v2[2] = {25.0,0.0};
  865.     static float v3[2] = {25.0,5.5};
  866.     static float v4[2] = {0.0,5.5};
  867.     bgnpolygon();
  868.         cpack(DASH_GREY);
  869.         v2f(v1); v2f(v2);
  870.         v2f(v3); v2f(v4);
  871.     endpolygon();
  872.  
  873.     // draw top strip of dash background
  874.     static float w1[2] = {0.0,5.5};
  875.     static float w2[2] = {25.0,5.5};
  876.     static float w3[2] = {25.0,6.0};
  877.     static float w4[2] = {0.0,6.0};
  878.     cpack(0x101010);
  879.     bgnpolygon();
  880.         v2f(w1); v2f(w2); v2f(w3); v2f(w4);
  881.     endpolygon();
  882.  
  883. }
  884.  
  885.  
  886. void Cockpit::draw_hood(int display_mode) const
  887. {
  888.     Boolean last_zbuffer = getzbuffer();
  889.     Boolean last_backface = getbackface();
  890.     long last_shademodel = getsm();
  891.  
  892.     if (display_mode == RENDER_FILLED)
  893.     {
  894.         lmbind(LMODEL,1);
  895.         lmbind(LIGHT0,SUN);
  896.         shademodel(GOURAUD);
  897.         zbuffer(FALSE);
  898.         backface(TRUE);
  899.     }
  900.     
  901.     pushmatrix();
  902.  
  903.         // offset from eye position to center of hood
  904.         translate(1.5,-2.0,-2.0);
  905.  
  906.         pushmatrix();
  907. //            scale(4.5,0.1,4.0);
  908.             scale(6.0,0.1,5.0);
  909.             rotate(-200,'x');
  910.             if (display_mode)
  911.             {
  912.                 lmbind(MATERIAL, RED_METAL);
  913.                 fcylinder();
  914.             }
  915.             else
  916.             {
  917.                 cpack(0xFF);
  918.                 wcylinder();
  919.             }
  920.         popmatrix();
  921.  
  922.     popmatrix();
  923.  
  924.     if (display_mode == RENDER_FILLED)
  925.     {
  926.         lmbind(MATERIAL,0);
  927.         lmbind(LIGHT0,0);
  928.         lmbind(LMODEL,0);
  929.         shademodel(last_shademodel);
  930.         zbuffer(last_zbuffer);
  931.         backface(last_backface);
  932.     }
  933.  
  934. }
  935.  
  936.  
  937. void Cockpit::draw_steering_spokes(Boolean draw_it, float steering) const
  938. {
  939.     /// draw steering spokes
  940.     short spoke_rot = 200;
  941.  
  942.     pushmatrix();
  943.     
  944.         translate(_steering_pos[0], _steering_pos[1], _steering_pos[2]);
  945.         
  946.         rot(- steering*180.0/M_PI,'z');
  947.  
  948.         pushmatrix();
  949.             rotate(spoke_rot,'z');
  950.             draw_steering_spoke(draw_it);
  951.  
  952.             scale(-1.0,1.0,1.0);
  953.             draw_steering_spoke(draw_it);
  954.         popmatrix();
  955.  
  956.         pushmatrix();
  957.             rotate(-spoke_rot,'z');
  958.             draw_steering_spoke(draw_it);
  959.             
  960.             scale(-1.0,1.0,1.0);
  961.             draw_steering_spoke(draw_it);
  962.         popmatrix();
  963.  
  964.     popmatrix();
  965. }
  966.